﻿using System;
using System.Globalization;
using System.IO;
using LogNaga.Configuration;

namespace LogNaga.Logs
{
	/// <summary>
	/// 每天自动切割日志文件的Log扩展
	/// </summary>
	public class AutoCutFileLog : TextLog, IDisposable
	{
		private readonly string fileName;//路径
		private volatile bool disposed;
		private FileLog log;
		private long nextCutTicks;//下一次切割的时间
		private ExceptionFormatter exceptionFormatter;

		#region .ctor

		/// <summary>
		/// 创建一个<see cref="AutoCutFileLog"/>实例
		/// </summary>
		/// <param name="filePath">文件路径</param>
		public AutoCutFileLog(string fileName)
			:this(fileName, ExceptionFormatterHelper.Default)
		{ }

		/// <summary>
		/// 创建一个<see cref="AutoCutFileLog"/>实例
		/// </summary>
		/// <param name="filePath">文件路径</param>
		/// <param name="exceptionFormatter"><see cref="ExceptionFormatter"/>实例</param>
		public AutoCutFileLog(string fileName, ExceptionFormatter exceptionFormatter)
		{
			this.fileName = fileName;
			this.disposed = false;

			this.CreateFile();
			this.ResetNextCutTime();

			this.exceptionFormatter = exceptionFormatter;
		}

		#endregion

		#region override TextLog.WriteToDestination

		/// <summary>
		/// 记录错误内容到文件
		/// </summary>
		/// <param name="errorEntry"></param>
		public override void WriteToDestination(Error errorEntry)
		{
			CheckIfNeedToCutFile();
			this.log.Write(errorEntry);
		}

		#endregion

		#region Help Methods

		/// <summary>
		/// 创建log文件
		/// </summary>
		private void CreateFile()
		{
			if (this.log != null)
			{
				this.log.Dispose();
				this.log = null;
			}

			var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LoggingConfigurationSection.GetConfig().DirectoryName);
			if (!Directory.Exists(path)) Directory.CreateDirectory(path);

			path = Path.Combine(path, fileName);

			this.log = new FileLog(this.fileName + '_' + DateTime.Now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture) + ".log", true);
		}

		/// <summary>
		/// 重置下一次日志切割时间
		/// </summary>
		private void ResetNextCutTime()
		{
			this.nextCutTicks = DateTime.Now.Date.AddDays(1).Ticks;
		}

		/// <summary>
		/// 检查是否需要切割文件，如果需要的话就进行切割
		/// </summary>
		private void CheckIfNeedToCutFile()
		{
			if (DateTime.Now.Ticks > this.nextCutTicks)
			{
				this.CreateFile();
				this.ResetNextCutTime();
			}
		}

		#endregion

		#region Dispose

		/// <summary>
		/// Dispose
		/// </summary>
		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}

		/// <summary>
		/// Dispose
		/// </summary>
		/// <param name="disposing">is disposing</param>
		public virtual void Dispose(bool disposing)
		{
			if (this.disposed)
			{
				return;
			}

			try
			{
				if (disposing)
				{
					this.log.Dispose();
					this.log = null;
				}
			}
			finally
			{
				this.disposed = true;
			}
		}

		#endregion

		public override ExceptionFormatter GetExceptionFormatter()
		{
			return this.exceptionFormatter;
		}
	}
}
